<?php namespace wanghua\general_utility_tools_php\gpt\chat;

use wanghua\general_utility_tools_php\phpmailer\Exception;
use wanghua\general_utility_tools_php\tool\Tools;

class FastGPT extends BaseChat
{
    public $url = '';
    public $apiKey = '';
    public $model = '';
    public $chatId = '';
    public $detail = false;
    private $messages = [];

    public function __construct()
    {
    }

    /**
     * desc：定制个性
     * author：wh
     * @param array $customize
     */
    function setCustomize($customize = [])
    {
        if ($customize) {
            foreach ($customize as $item) {
                $this->messages[] = $item;
            }
        }
    }

    function setBefore($describe = [])
    {
        if ($describe) {
            foreach ($describe as $item) {
                $this->messages[] = $item;
            }
        }
    }

    function setAfter($describe = [])
    {
        if ($describe) {
            foreach ($describe as $item) {
                $this->messages[] = $item;
            }
        }
    }

    private function check()
    {
        if (empty($this->url) || empty($this->apiKey)) {
            throw new Exception('PARAMS ERROR');
        }
    }

    function chat($question = '', $config = [], &$answer_json_arr)
    {
        $answer = '';
        $this->curlPostChat($question, $config, function ($ch, $data) use ($question, &$answer, &$answer_json_arr) {
            $answer_json_arr[] = $data;
            echo $data;
            ob_flush();
            flush();
            return strlen($data);
        });
    }

    private function curlPostChat($question = '', $config = [], $callback)
    {
        $this->check();
        $url = $this->url;;
        $apiKey = $this->apiKey;
        $model = $this->model;
        $chatId = $this->chatId;
        $detail = $this->detail;
        $headers = ["Authorization: Bearer $apiKey", 'Accept: application/json', 'Content-Type: application/json',];
        $post_msg_body = ['detail' => $detail, 'stream' => true,];
        if ($detail) {
            $post_msg_body['detail'] = $detail;
        }
        if ($chatId) {
            $post_msg_body['chatId'] = $chatId;
        }
        if ($model) {
            $post_msg_body['model'] = $model;
        }
        if ($config) {
            foreach ($config as $key => $val) {
                $post_msg_body[$key] = $val;
            }
        }
        if ($question) {
            $this->messages[] = ["role" => "user", "content" => $question];
        }
        $post_msg_body['messages'] = $this->messages;
        $postData = json_encode($post_msg_body);
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
        curl_setopt($ch, CURLOPT_POST, 1);
        curl_setopt($ch, CURLOPT_POSTFIELDS, $postData);
        curl_setopt($ch, CURLOPT_WRITEFUNCTION, $callback);
        curl_exec($ch);
    }

    private function parseData($data)
    {
        if (@json_decode($data)->choices[0]->message->content) {
            return json_decode($data)->choices[0]->message->content;
        }
        $data = str_replace('data: {', '{', $data);
        $data = rtrim($data, "\n\n");
        if (strpos($data, 'data: [DONE]') !== false) {
            return 'data: [DONE]';
        } else {
            if (false !== strpos($data, "\n\n")) {
                $exp_arr = explode("\n\n", $data);
                $str = '';
                try {
                    for ($i = 0; $i < count($exp_arr) - 1; $i++) {
                        $jsondecode_arr = json_decode($exp_arr[$i], true);
                        $str .= $jsondecode_arr['choices'][0]['delta']['content'];
                    }
                    return $str;
                } catch (\Exception $e) {
                    return $str;
                }
            }
            $data = @json_decode($data, true);
            if (!is_array($data)) {
                return '';
            }
            if ($data['choices'][0]['finish_reason'] == 'stop') {
                return 'data: [DONE]';
            } elseif ($data['choices'][0]['finish_reason'] == 'length') {
                return 'data: [CONTINUE]';
            }
            return $data['choices'][0]['delta']['content'] ?? '';
        }
    }
}